home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 May: Tool Chest / Dev.CD May 98 TC.toast / Tool Chest / Development Kits / HyperCard Related / APDA HyperCard Toolkits / CD Audio Toolkit 1.0 / Source / Programs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-07  |  12.9 KB  |  548 lines  |  [TEXT/MPS ]

  1. /*
  2.     Programs.c    -     support routines for manipulating the CD Remote Programs
  3.                     file.
  4.     ©Apple Computer, Inc. 1988
  5.     All Rights Reserved.
  6. */
  7.  
  8. #include "cd.h"
  9. #include "SysEqu.h"
  10.  
  11. typedef struct {
  12.     unsigned long    index;
  13.     short            rsrcID;
  14. }    entryStruct;
  15.  
  16.  
  17.  
  18.  
  19. /************************************************************************
  20.  *
  21.  *  Function:        OpenSystemResFile
  22.  *
  23.  *  Purpose:        open a resource file that's in the system folder
  24.  *
  25.  *  Returns:        whatever would be returned by OpenResFile()
  26.  *                    -1 indicates an error.  You must call ResError()
  27.  *                    to find the real error.
  28.  *                    Any other value is the refNum for that resource file.
  29.  *
  30.  *  Side Effects:    opens the specified file.
  31.  *
  32.  *  Description:    Save the current volume.  Get the volume of the
  33.  *                    system folder.  Set that as the default volume.
  34.  *                    Open the file.  Restore all the settings.
  35.  *
  36.  ************************************************************************/
  37. int
  38. OpenSystemResFile(fileName)
  39. Str255    *fileName;
  40. {
  41.     int            curVol;
  42.     OSErr        result;
  43.     SysEnvRec    theWorld;
  44.     
  45.     GetVol(nil, &curVol);
  46.  
  47.     result = SysEnvirons(curSysEnvVers, &theWorld);
  48.     if (result == noErr)
  49.     {
  50.         SetVol(nil, theWorld.sysVRefNum);
  51.     
  52.         result = OpenResFile(fileName);
  53.     
  54.         SetVol(nil, curVol);
  55.     }
  56.     
  57.     return result;
  58. }
  59.  
  60.  
  61. /************************************************************************
  62.  *
  63.  *  Function:        FindIndex
  64.  *
  65.  *  Purpose:        find a resource ID, given an index
  66.  *
  67.  *  Returns:        boolean
  68.  *                    true if the index existed
  69.  *                    false if no such index.  This means we've never
  70.  *                    seen this disc before.
  71.  *
  72.  *  Side Effects:    fills in rsrcID.
  73.  *
  74.  *  Description:    the IndX resource contains 8 bytes of header, 
  75.  *                    followed by an array of 6 byte entries.
  76.  *
  77.  *                    The first two bytes of the header are the
  78.  *                    version of this resource, and will be 0x0010
  79.  *                    or 0x0011.  Don't check--it will change someday.
  80.  *                    The next two bytes are the number of entries.
  81.  *
  82.  *                    In the entries, the first byte is the number of 
  83.  *                    tracks on the disc. The next three bytes are the
  84.  *                    index we're trying to match. The last two bytes
  85.  *                    are the resource ID of both the 'STR#' resource
  86.  *                    and the 'ProG' resource (telling the desk
  87.  *                    accessory in what order to play the tracks).
  88.  *                    Fill in rsrcID with that number, if found.
  89.  *                    
  90.  *
  91.  ************************************************************************/
  92. Boolean
  93. FindIndex(index, rsrcID)
  94. unsigned long    index;
  95. short            *rsrcID;
  96. {
  97.     short        numEntries;
  98.     entryStruct    *entryPtr;
  99.     short        *headerPtr;
  100.     Boolean        foundIt;
  101.     Handle        indexHandle;
  102.     
  103.     foundIt = false;
  104.     *rsrcID = 0;
  105.     
  106.     indexHandle = Get1Resource('IndX', 128);
  107.     if (indexHandle == nil)
  108.         return false;
  109.     
  110.     HLock(indexHandle);
  111.     headerPtr = (short  *) *indexHandle;
  112.             
  113.     headerPtr++;
  114.     numEntries = *headerPtr++;
  115.     entryPtr = (entryStruct *)headerPtr;
  116.     
  117.     while (numEntries > 0 & foundIt == false)
  118.     {
  119.         if ((entryPtr->index & 0x00FFFFFF) == index)
  120.         {
  121.             *rsrcID = entryPtr->rsrcID;
  122.             foundIt = true;
  123.         }
  124.         entryPtr++;
  125.         numEntries--;
  126.     }
  127.     
  128.     HUnlock(indexHandle);
  129.     
  130.     ReleaseResource(indexHandle);
  131.     return (foundIt);
  132. }
  133.  
  134. /************************************************************************
  135.  *
  136.  *  Function:        AddDisc
  137.  *
  138.  *  Purpose:        add a CD to the CD Remote Programs file
  139.  *
  140.  *  Returns:        OSErr
  141.  *                    noErr            if everything went well.
  142.  *                    something else    whatever was returned by the call
  143.  *                                    that gave us the error.
  144.  *
  145.  *  Side Effects:    Adds an IndX entry and a ProG and STR# resource 
  146.  *                    to the file 'CD Remote Programs'
  147.  *
  148.  *  Description:    Get the IndX resource #128 (famous value).
  149.  *                    Get a new resource number, using Unique1ID.  Get
  150.  *                    a handle for the new IndX resource. (It will be six
  151.  *                    bytes greater than the current one, since that's
  152.  *                    the size of an IndX entry.)  The entry contains
  153.  *                        the number of tracks (byte)
  154.  *                        the total number of blocks on disc (3 bytes)
  155.  *                        unique resource ID we just got (2 bytes)
  156.  *                    Store that away.  Get enough room for the ProG
  157.  *                    resource (2 bytes per track, plus 2 byte header).
  158.  *                    Initialize that to default value (we don't yet
  159.  *                    support Program playing.)  The ID of this ProG is
  160.  *                    equal to our unique ID.
  161.  *                    For the STR#, build a default using the STR
  162.  *                    resources for the words 'Volume title' and
  163.  *                    'Track N'.  Build the STR# and add it, of ID equal
  164.  *                    to our unique ID.
  165.  *                    
  166.  *
  167.  ************************************************************************/
  168. OSErr
  169. AddDisc(discID, numberOfTracks)
  170. unsigned long    discID;
  171. short            numberOfTracks;
  172. {
  173.     OSErr    result;
  174.     short    uniqueID;    /* for ProG and STR# IDs */
  175.     
  176.     result = noErr;
  177.     
  178.     if (result == noErr)
  179.         result = AddIndX(discID, numberOfTracks, &uniqueID);
  180.     
  181.     if (result == noErr)
  182.         result = AddTitles(uniqueID, numberOfTracks);
  183.  
  184.     if (result == noErr)
  185.         result = AddProG(uniqueID, numberOfTracks);
  186.     
  187.     return result;
  188. }
  189.  
  190.  
  191. /************************************************************************
  192.  *
  193.  *  Function:        AddIndX
  194.  *
  195.  *  Purpose:        Add a new IndX entry
  196.  *
  197.  *  Returns:        OSErr
  198.  *                    noErr, unless somebody we call goes bad.
  199.  *
  200.  *  Side Effects:    size of IndX resource 128 grows by 6 bytes
  201.  *
  202.  *  Description:    Get the 'IndX' resource number 128.  Figure out the
  203.  *                    size of resource.  Allocate a handle of that size
  204.  *                    plus six bytes (1 byte number of tracks, 3 bytes
  205.  *                    disk id, 2 bytes resource number).  Copy from the
  206.  *                    original resource to the new one.
  207.  *
  208.  ************************************************************************/
  209. OSErr
  210. AddIndX(discID, numTracks, uniqueID)
  211. unsigned long    discID;
  212. short            numTracks;        /* number of tracks on this disc. */
  213. short            *uniqueID;
  214. {
  215.     Handle            indxHandle;
  216.     short            unique;
  217.     Size            indxSize;
  218.     entryStruct        *indexPtr;
  219.     OSErr            result;
  220.     short            *headerPtr;
  221.     unsigned long    newIndex;
  222.     short            numEntries;
  223.     
  224.     
  225.     indxHandle = nil;
  226.     result = noErr;
  227.     
  228.     indxHandle = Get1Resource('IndX', 128);
  229.  
  230.     if (indxHandle == nil)
  231.         result = ResError();
  232.         
  233.     if (result == noErr)
  234.     {
  235.         do {
  236.             unique = Unique1ID('ProG');
  237.         } while (unique < 128);        /* don't want system rsrc ID. see IM I-121 */
  238.     }
  239.     
  240.     if (result == noErr)
  241.     {
  242.         indxSize = GetHandleSize(indxHandle) + 6;
  243.         SetHandleSize(indxHandle, indxSize);
  244.         result = MemError();
  245.     }
  246.     HLock(indxHandle);
  247.     headerPtr = (short  *) *indxHandle;
  248.         
  249.     if (result == noErr)
  250.     {
  251.         headerPtr++;    /* skip version number */
  252.         numEntries = *headerPtr;
  253.         *headerPtr = numEntries+1;
  254.         headerPtr++;
  255.         indexPtr = (entryStruct *)headerPtr;
  256.     
  257.         newIndex = (discID & 0x00FFFFFF) | ((long)numTracks << 24);
  258.         indexPtr[numEntries].index = newIndex;
  259.         indexPtr[numEntries].rsrcID = unique;
  260.         *uniqueID = unique;
  261.     }
  262.     HUnlock(indxHandle);
  263.  
  264.     if (result == noErr)
  265.     {
  266.         ChangedResource(indxHandle);
  267.         result = ResError();
  268.     }
  269.     if (result == noErr)
  270.     {
  271.         WriteResource(indxHandle);
  272.         result = ResError();
  273.     }
  274.     
  275.     ReleaseResource(indxHandle);
  276.     return result;
  277. }
  278.  
  279.  
  280. /************************************************************************
  281.  *
  282.  *  Function:        AddProG
  283.  *
  284.  *  Purpose:        Add a new ProG resource for a CD
  285.  *
  286.  *  Returns:        OSErr
  287.  *                    usually noErr, but could have problems creating
  288.  *                    the new ProG resource.
  289.  *
  290.  *  Side Effects:    Modifies "CD Remote Programs" file to add new
  291.  *                    resource.
  292.  *
  293.  *  Description:    A 'ProG' resource is made as follows:
  294.  *                    1)    a word giving the number of tracks on this disc
  295.  *                        in hexadecimal.
  296.  *                    2)    a two-byte entry for each track, containing
  297.  *                        i)     a byte indicating whether to play this track
  298.  *                            or not (1 = play, 0 = not)
  299.  *                        ii)    a byte containing the track number in BCD.
  300.  *                    We create such a default ProG resource for the disc
  301.  *                    in question.
  302.  *
  303.  ************************************************************************/
  304. OSErr
  305. AddProG(rsrcID, numTracks)
  306. short    rsrcID;
  307. short    numTracks;
  308. {
  309.     Handle    progHandle;
  310.     Handle    resHandle;
  311.     OSErr    result;
  312.     Size    progSize;
  313.     short    *progPtr;
  314.     short    i;
  315.     
  316.     result = noErr;
  317.     progSize = (numTracks * 2) + 2;        /* 2 bytes per track + header */
  318.     
  319.     progHandle = NewHandle(progSize);
  320.     if (progHandle == nil)
  321.         result = MemError();
  322.     
  323.     HLock(progHandle);
  324.     
  325.     if (result == noErr)
  326.     {
  327.         progPtr = (short *) *progHandle;
  328.         progPtr[0] = numTracks;
  329.         for (i = 1; i <= numTracks; i++)
  330.             progPtr[i] = (short) DECIMAL2BCD(i) | 0x0100;
  331.     }
  332.     
  333.     HUnlock(progHandle);
  334.     if (result == noErr)
  335.     {
  336.         AddResource(progHandle, 'ProG', rsrcID, "\p");
  337.         result = ResError();
  338.     }
  339.     if (result == noErr)
  340.     {
  341.         resHandle = GetResource('ProG', rsrcID);
  342.         WriteResource(resHandle);
  343.         result = ResError();
  344.         ReleaseResource(resHandle);
  345.     }
  346.     
  347.     return result;
  348. }
  349.  
  350. /************************************************************************
  351.  *
  352.  *  Function:        AddTitles
  353.  *
  354.  *  Purpose:        add default song titles for this disc
  355.  *
  356.  *  Returns:        OSErr
  357.  *                    usually noErr, but could have problems creating
  358.  *                    the new STR# resource.
  359.  *
  360.  *  Side Effects:    Modifies "CD Remote Programs" file to add new
  361.  *                    resource.
  362.  *
  363.  *  Description:    A 'STR#' resource consists of a two byte value which
  364.  *                    is the number of strings, followed by the strings.
  365.  *                    Each string is a pascal string (i.e. with a length
  366.  *                    byte preceeding it.)  We generated such a resource
  367.  *                    by getting a Handle for the header, and using
  368.  *                    Munger (IM I-468) to add the strings.
  369.  *
  370.  ************************************************************************/
  371. OSErr
  372. AddTitles(rsrcID, numTracks)
  373. short    rsrcID;
  374. short    numTracks;
  375. {
  376.     Handle    stringHandle;
  377.     Handle    resHandle;
  378.     OSErr    result;
  379.     Size    stringSize;
  380.     short    *stringPtr;
  381.     short    i;
  382.     short    mungerReturn;
  383.     Str255    trackName;
  384.     char    trackNumber[3];        /* 01 - 99 inclusive */
  385.     Str31    discTitle;
  386.     Str31    trackTitle;
  387.     
  388.     result = noErr;
  389.     stringSize = 2;        /* 2 byte header containing number of strings */
  390.     
  391.     GetIndString(discTitle, STR_ID, DISKTITLE);
  392.     if (discTitle == (Str31)0)
  393.         result = ResError();
  394.  
  395.     GetIndString(trackTitle, STR_ID, TRACKTITLE);
  396.     if (trackTitle == (Str31)0)
  397.         result = ResError();
  398.     p2cstr(trackTitle);
  399.  
  400.     if (result == noErr)
  401.     {
  402.         stringHandle = NewHandle(stringSize);
  403.         if (stringHandle == nil)
  404.             result = MemError();
  405.     }
  406.     
  407.     if (result == noErr)
  408.     {
  409.         HLock(stringHandle);    
  410.         stringPtr = (short *) *stringHandle;
  411.         stringPtr[0] = numTracks+1;        /* add title, too */
  412.         HUnlock(stringHandle);
  413.         mungerReturn = Munger(stringHandle,  GetHandleSize(stringHandle), 
  414.                                 "\p", 0L, discTitle, 11L);
  415.         for (i = 1; i <= numTracks; i++)
  416.         {
  417.             strcpy(trackName, trackTitle);
  418.             ltoa((long) i, trackNumber);
  419.             strcat(trackName, trackNumber);
  420.             c2pstr(trackName);
  421.             mungerReturn = Munger(stringHandle, GetHandleSize(stringHandle), 
  422.                                 "\p", 0L, trackName, trackName[0]+1);
  423.         }
  424.     }
  425.  
  426.     if (result == noErr)
  427.     {
  428.         AddResource(stringHandle, 'STR#', rsrcID, "\p");
  429.         result = ResError();
  430.     }
  431.     if (result == noErr)
  432.     {
  433.         resHandle = GetResource('STR#', rsrcID);
  434.         WriteResource(resHandle);
  435.         result = ResError();
  436.         ReleaseResource(resHandle);
  437.     }
  438.     
  439.     return result;
  440. }
  441.  
  442.  
  443. /************************************************************************
  444.  *
  445.  *  Function:        GetNumberTracks
  446.  *
  447.  *  Purpose:        report how many tracks are on this CD
  448.  *
  449.  *  Returns:        OSErr.  Probably either
  450.  *                        noErr        everything's hunky-dory!
  451.  *                        paramErr    you messed up the call somehow.
  452.  *
  453.  *  Side Effects:    none
  454.  *
  455.  *  Description:    Simply call the driver.
  456.  *
  457.  ************************************************************************/
  458. OSErr
  459. GetNumberTracks(refNum, numberTracks)
  460. short    refNum;
  461. short    *numberTracks;
  462. {
  463.     CDParam    myPB;
  464.     OSErr    result;
  465.     
  466.     myPB.ioCompletion = 0;
  467.     myPB.ioNamePtr = (char *) 0;
  468.     myPB.ioVRefNum = 1;
  469.     myPB.ioCRefNum = refNum;
  470.     myPB.csCode = READTOC;
  471.     myPB.csParam[0] = 0;
  472.     myPB.csParam[1] = 1;
  473.     
  474.     result = PBControl(&myPB, false);
  475.     
  476.     if (result == noErr)
  477.         *numberTracks = (short) BCD2DECIMAL(myPB.csParam[1]);
  478.     return result;
  479. }
  480.  
  481.  
  482. /************************************************************************
  483.  *
  484.  *  Function:        IDDisc
  485.  *
  486.  *  Purpose:        return total time on this disc as unique ID
  487.  *
  488.  *  Returns:        OSErr
  489.  *                    either noErr if everything was okay
  490.  *                    or some parameter error from driver call.
  491.  *
  492.  *  Side Effects:
  493.  *                    fills in discID
  494.  *
  495.  *  Description:
  496.  *                    call the driver ReadTOC call to get lead-out time.
  497.  *                    Return this time as the unique id for this disc.
  498.  *
  499.  ************************************************************************/
  500. OSErr
  501. IDDisc(refNum, discID)
  502. short    refNum;
  503. unsigned long    *discID;
  504. {
  505.     CDIDParam    myPB;
  506.     OSErr    result;
  507.     
  508.     myPB.ioCompletion = 0;
  509.     myPB.ioNamePtr = (char *) 0;
  510.     myPB.ioVRefNum = 1;
  511.     myPB.ioCRefNum = refNum;
  512.     myPB.csCode = READTOC;
  513.     myPB.discID = 0x00020000;    /* request lead-out time */
  514.     
  515.     result = PBControl((ParmBlkPtr)&myPB, false);
  516.     
  517.     if (result == noErr)
  518.         *discID = myPB.discID >> 8;
  519.     else
  520.         *discID = 0;
  521.     return result;
  522. }
  523.  
  524.  
  525. /************************************************************************
  526.  *
  527.  *  Function:        HandleToPString
  528.  *
  529.  *  Purpose:        copy contents of handle to pascal string
  530.  *
  531.  *  Returns:        void
  532.  *
  533.  *  Side Effects:    pointer p's contents are made those of handle h
  534.  *
  535.  *  Description:    We assume that you've allocated space large enough
  536.  *                    to store the contents.
  537.  *
  538.  ************************************************************************/
  539. void
  540. HandleToPString(h, p)
  541. Handle    h;
  542. Ptr        p;
  543. {
  544.     strcpy(p, *h);
  545.     c2pstr(p);
  546. }
  547.  
  548.